﻿using System;
using System.IO;
using System.Linq;

namespace U.Comm.IO
{
    /// <summary>
    /// 应用于 本地文件存储 的类，执行常规的文件操作，支持Web
    /// </summary>
    public class Storage
    {
        private const string InvalidCharactersInFileName = @"\,/,:,*,?,"",<,>,|";

        /// <summary>
        /// 保存数据为临时文件
        /// </summary>
        /// <param name="data"></param>
        /// <returns>返回临时文件位置，失败为空</returns>
        public string SaveFileAsTemporary(byte[] data)
        {
            var path = Path.GetTempFileName();
            return SaveFile(path, data) ? path : string.Empty;
        }

        /// <summary>
        /// 保存文件到指定路径，如已存在，则覆盖
        /// </summary>
        /// <param name="filePath"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool SaveFile(string filePath, byte[] data)
        {
            return SaveFile(filePath, data,true);
        }

        /// <summary>
        /// 保存文件到指定路径
        /// </summary>
        /// <param name="filePath">完整文件路径，包含文件名</param>
        /// <param name="data"></param>
        /// <param name="overWrite"></param>
        /// <returns></returns>
        public bool SaveFile(string filePath, byte[] data, bool overWrite)
        {
            if (overWrite)
            {
                if (!DeleteFile(filePath))
                {
                    return false;
                }
            }
            else
            {
                if (File.Exists(filePath))
                {
                    return true;
                }
            }
            
            var folderPath = filePath.Substring(0, filePath.LastIndexOf('\\'));
            if (!EnsureFolderExists(folderPath)) return false;

            var isSucceed = true;
            var file = new FileInfo(filePath);
            var fs = file.Create();
            try
            {
                fs.Write(data,0,data.Length);
            }
            catch (Exception)
            {
                isSucceed = false;
            }
            finally
            {
                fs.Close();
            }
            return isSucceed;
        }


        public bool CopyFile(string sourceFilePath, string targetFilePath, bool overWrite)
        {
            return File.Exists(sourceFilePath) && SaveFile(targetFilePath, File.ReadAllBytes(sourceFilePath), overWrite);
        }

        public bool MoveFile(string sourceFilePath, string targetFilePath,bool overWrite)
        {
            return CopyFile(sourceFilePath, targetFilePath, overWrite) && DeleteFile(sourceFilePath);
        }

        public bool DeleteFile(string filePath)
        {
            try
            {
                if (File.Exists(filePath))
                {
                    File.Delete(filePath);
                    return true;
                }
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        /// <summary>
        /// 确保指定的路径存在，如果不存在，则创建相应的文件夹，操作系统不支持的非法字符将被过滤，若过滤后为空，则使用下划线代替
        /// </summary>
        /// <param name="folderPath"></param>
        /// <returns></returns>
        public bool EnsureFolderExists(string folderPath)
        {
            try
            {
                var paths = folderPath.Split('\\');
                var path = paths[0] + "\\";
                for (var i = 1; i < paths.Length; i++)
                {
                    var folderName = GetSafeFileName(paths[i]);
                    if (string.IsNullOrEmpty(folderName)) continue;
                    path += folderName + "\\";
                    if (!Directory.Exists(path)) Directory.CreateDirectory(path);
                }
                return true;
            }
            catch (Exception)
            {

                return false;
            }
        }

        /// <summary>
        /// 获取安全的文件夹、文件名
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        private string GetSafeFileName(string str)
        {
            if (!string.IsNullOrEmpty(str))
            {
                var result = InvalidCharactersInFileName.Split(',').Aggregate(str, (current, _char) => current.Replace(_char, ""));
                return string.IsNullOrEmpty(result) ? "_" : result;
            }
            return "";
        }

    }
}
